package com.imut.lagain.service.impl;

import jakarta.annotation.Resource;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.imut.lagain.entity.Notification;
import com.imut.lagain.entity.NotificationTemplate;
import com.imut.lagain.entity.WechatNotification;
import com.imut.lagain.mapper.WechatNotificationMapper;
import com.imut.lagain.repository.WechatNotificationRepository;
import com.imut.lagain.service.IWechatNotificationService;

import org.springframework.beans.factory.annotation.Autowired;
import com.imut.lagain.config.WeChatConfig;
import com.imut.lagain.util.WechatUtil;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 微信通知记录服务实现类
 */
@Service
public class WechatNotificationServiceImpl extends ServiceImpl<WechatNotificationMapper, WechatNotification> implements IWechatNotificationService {

    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(WechatNotificationServiceImpl.class);

    @Autowired
    private WechatNotificationRepository wechatNotificationRepository;

    @Resource
    private WeChatConfig weChatConfig;

    @Resource
    private RestTemplate restTemplate;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private ObjectMapper objectMapper;

    private static final String ACCESS_TOKEN_URL = "%s%s?grant_type=client_credential&appid=%s&secret=%s";
    private static final String TEMPLATE_MESSAGE_URL = "%s%s?access_token=%s";
    private static final String CUSTOM_MESSAGE_URL = "%s%s?access_token=%s";
    private static final String ACCESS_TOKEN_CACHE_KEY = "wechat:access_token";
    private static final int ACCESS_TOKEN_EXPIRE_TIME = 7000;

    @Override
    public IPage<WechatNotification> findByUserIdAndEventType(Long userId, String eventType, Page<WechatNotification> page) {
        QueryWrapper<WechatNotification> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId)
                   .eq("event_type", eventType)
                   .orderByDesc("create_time");
        return this.page(page, queryWrapper);
    }

    @Override
    public IPage<WechatNotification> findBySendStatus(String sendStatus, Page<WechatNotification> page) {
        QueryWrapper<WechatNotification> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("send_status", sendStatus)
                   .orderByDesc("create_time");
        return this.page(page, queryWrapper);
    }

    @Override
    public List<WechatNotification> findPendingNotifications(int size) {
        QueryWrapper<WechatNotification> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("send_status", "PENDING")
                   .orderByAsc("create_time")
                   .last("LIMIT " + size);
        return this.list(queryWrapper);
    }

    @Override
    public boolean updateSendStatus(Long id, String sendStatus, LocalDateTime sendTime) {
        WechatNotification notification = this.getById(id);
        if (notification != null) {
            notification.setSendStatus(sendStatus);
            notification.setSendTime(sendTime);
            return this.updateById(notification);
        }
        return false;
    }

    @Override
    public List<Object[]> countBySendStatus() {
        return wechatNotificationRepository.countBySendStatus();
    }

    @Override
    public List<WechatNotification> getPendingNotificationsByUserId(Long userId, int size) {
        QueryWrapper<WechatNotification> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId)
                   .eq("send_status", "PENDING")
                   .orderByAsc("create_time")
                   .last("LIMIT " + size);
        return this.list(queryWrapper);
    }

    @Override
    public IPage<WechatNotification> getWechatNotificationsByUserId(Long userId, Page<WechatNotification> page, String eventType, String sendStatus) {
        QueryWrapper<WechatNotification> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId);
        
        if (eventType != null && !eventType.trim().isEmpty()) {
            queryWrapper.eq("event_type", eventType);
        }
        
        if (sendStatus != null && !sendStatus.trim().isEmpty()) {
            queryWrapper.eq("send_status", sendStatus);
        }
        
        queryWrapper.orderByDesc("create_time");
        return this.page(page, queryWrapper);
    }

    @Override
    public Map<String, Object> getNotificationStatsByUserId(Long userId) {
        Map<String, Object> stats = new HashMap<>();
        
        QueryWrapper<WechatNotification> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId);
        
        long total = this.count(queryWrapper);
        stats.put("total", total);
        
        QueryWrapper<WechatNotification> pendingWrapper = new QueryWrapper<>();
        pendingWrapper.eq("user_id", userId).eq("send_status", "PENDING");
        long pending = this.count(pendingWrapper);
        stats.put("pending", pending);
        
        QueryWrapper<WechatNotification> sentWrapper = new QueryWrapper<>();
        sentWrapper.eq("user_id", userId).eq("send_status", "SENT");
        long sent = this.count(sentWrapper);
        stats.put("sent", sent);
        
        QueryWrapper<WechatNotification> failedWrapper = new QueryWrapper<>();
        failedWrapper.eq("user_id", userId).eq("send_status", "FAILED");
        long failed = this.count(failedWrapper);
        stats.put("failed", failed);
        
        return stats;
    }

    @Override
    public boolean sendTemplateMessage(Notification notification, NotificationTemplate template, Map<String, Object> data) {
        try {
            String accessToken = getAccessToken();
            if (accessToken == null) {
                log.error("获取微信Access Token失败");
                return false;
            }

            Map<String, Object> messageData = new HashMap<>();
            messageData.put("touser", notification.getUserId().toString());
            messageData.put("template_id", template.getTemplateId());
            messageData.put("url", template.getRedirectUrl());
            messageData.put("topcolor", "#FF0000");
            messageData.put("data", buildTemplateData(template, data));

            if (template.getMiniProgramPage() != null && !template.getMiniProgramPage().isEmpty()) {
                Map<String, Object> miniProgram = new HashMap<>();
                miniProgram.put("appid", weChatConfig.getMiniProgramAppId());
                miniProgram.put("pagepath", template.getMiniProgramPage());
                messageData.put("miniprogram", miniProgram);
            }

            return sendCustomMessage(accessToken, messageData);
        } catch (Exception e) {
            log.error("发送模板消息失败", e);
            return false;
        }
    }

    @Override
    public boolean sendTextMessage(String openId, String content) {
        try {
            String accessToken = getAccessToken();
            if (accessToken == null) {
                return false;
            }

            Map<String, Object> messageData = new HashMap<>();
            messageData.put("touser", openId);
            messageData.put("msgtype", "text");
            
            Map<String, Object> textData = new HashMap<>();
            textData.put("content", content);
            messageData.put("text", textData);

            return sendCustomMessage(accessToken, messageData);
        } catch (Exception e) {
            log.error("发送文本消息失败", e);
            return false;
        }
    }

    @Override
    public boolean sendImageMessage(String openId, String mediaId) {
        return false;
    }

    @Override
    public boolean sendVoiceMessage(String openId, String mediaId) {
        return false;
    }

    @Override
    public boolean sendVideoMessage(String openId, String mediaId, String title, String description) {
        return false;
    }

    @Override
    public boolean sendMusicMessage(String openId, String title, String description, String musicUrl, String hqMusicUrl, String thumbMediaId) {
        return false;
    }

    @Override
    public boolean sendNewsMessage(String openId, String title, String description, String url, String picUrl) {
        return false;
    }

    @Override
    public String getAccessToken() {
        try {
            String cachedToken = (String) redisTemplate.opsForValue().get(ACCESS_TOKEN_CACHE_KEY);
            if (cachedToken != null && !cachedToken.isEmpty()) {
                return cachedToken;
            }
            return refreshAccessToken();
        } catch (Exception e) {
            log.error("获取Access Token失败", e);
            return null;
        }
    }

    @Override
    public String refreshAccessToken() {
        try {
            String url = String.format(ACCESS_TOKEN_URL, 
                weChatConfig.getApiBaseUrl(), 
                "/cgi-bin/token", 
                weChatConfig.getAppid(), 
                weChatConfig.getSecret());
            
            ResponseEntity<Map> response = restTemplate.getForEntity(url, Map.class);
            Map<String, Object> result = response.getBody();
            
            if (result != null && result.containsKey("access_token")) {
                String accessToken = result.get("access_token").toString();
                Integer expiresIn = Integer.parseInt(result.get("expires_in").toString());
                
                redisTemplate.opsForValue().set(ACCESS_TOKEN_CACHE_KEY, accessToken, 
                    Math.min(expiresIn - 200, ACCESS_TOKEN_EXPIRE_TIME), TimeUnit.SECONDS);
                
                log.info("微信Access Token刷新成功，有效期: {}秒", expiresIn);
                return accessToken;
            } else {
                log.error("刷新Access Token失败: {}", result);
                return null;
            }
        } catch (Exception e) {
            log.error("刷新Access Token异常", e);
            return null;
        }
    }

    @Override
    public String uploadTempMedia(String type, String filePath) {
        return null;
    }

    @Override
    public String uploadPermanentMedia(String type, String filePath, String title, String introduction) {
        return null;
    }

    @Override
    public Map<String, Object> getUserInfo(String openId) {
        return null;
    }

    @Override
    public boolean createMenu(String menuJson) {
        return false;
    }

    @Override
    public boolean deleteMenu() {
        return false;
    }

    @Override
    public Map<String, Object> getMenu() {
        return null;
    }

    @Override
    public boolean setIndustry(String industryId1, String industryId2) {
        return false;
    }

    public String getTemplateId(String templateIdShort) {
        return null;
    }

    public Map<String, Object> getAllPrivateTemplate() {
        return null;
    }

    @Override
    public boolean deleteTemplate(String templateId) {
        return false;
    }

    private Map<String, Object> buildTemplateData(NotificationTemplate template, Map<String, Object> data) {
        Map<String, Object> templateData = new HashMap<>();
        
        if (data != null) {
            for (Map.Entry<String, Object> entry : data.entrySet()) {
                Map<String, Object> item = new HashMap<>();
                item.put("value", entry.getValue());
                item.put("color", "#173177");
                templateData.put(entry.getKey(), item);
            }
        }
        
        return templateData;
    }

    private boolean sendCustomMessage(String accessToken, Map<String, Object> messageData) {
        try {
            String url = String.format(CUSTOM_MESSAGE_URL, weChatConfig.getApiBaseUrl(), "/cgi-bin/message/custom/send", accessToken);
            
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            
            String jsonData = objectMapper.writeValueAsString(messageData);
            HttpEntity<String> entity = new HttpEntity<>(jsonData, headers);
            
            ResponseEntity<Map> response = restTemplate.postForEntity(url, entity, Map.class);
            Map<String, Object> result = response.getBody();
            
            if (result != null && "0".equals(result.get("errcode").toString())) {
                log.info("微信消息发送成功");
                return true;
            } else {
                log.error("微信消息发送失败: {}", result);
                return false;
            }
        } catch (Exception e) {
            log.error("发送微信消息异常", e);
            return false;
        }
    }
    
    @Override
    public boolean checkSignature(String signature, String timestamp, String nonce, String token) {
        // 实现微信签名验证逻辑
        log.info("验证微信签名: signature={}, timestamp={}, nonce={}", signature, timestamp, nonce);
        return true;
    }
    
    @Override
    public String handleEvent(String xmlData) {
        // 实现事件处理逻辑
        log.info("处理微信事件: {}", xmlData);
        return "success";
    }
    
    @Override
    public String handleMessage(String xmlData) {
        // 实现消息处理逻辑
        log.info("处理微信消息: {}", xmlData);
        return "success";
    }
}